package com.xd.springboot.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;

@Aspect
@Component
public class LogAspectHandle {

    private  static  final Logger log= LoggerFactory.getLogger(LogAspectHandle.class);

    //1 * 返回值类型为所有类型
    //2  * 所有类
    //3 * 所有方法
    // .. 任何参数
    @Pointcut("execution(* com.xd.springboot.controller..*.*(..))")
    public  void pointCut()
    {

    }

    //针对某个注解
    @Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")
    public void annotationCut() {

    }

    @Before("pointCut()")
    public  void doBefore(JoinPoint joinPoint)
    {
        log.info("=====dobefore开始执行====");
        Signature signature=joinPoint.getSignature();
        String declaringTypeName =signature.getDeclaringTypeName();
        String fullName = signature.getName();
        log.info("即将执行的方法为：{}，属于{}包",fullName,declaringTypeName);

        ServletRequestAttributes attributes=(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request=attributes.getRequest();
        String url=request.getRequestURL().toString();
        String ip=request.getRemoteAddr();
        log.info("用户请求的URL为{}，IP地址为{}",url,ip);
    }

    //JointPoint 对象很有用，可以用它来获取一个签名，然后利用签名可以获取请求的包名、方法名，包括参数

    @After("pointCut()")
    public  void doAfter(JoinPoint joinPoint){
        log.info("============doAfter执行====");
        Signature signature=joinPoint.getSignature();
        String method=signature.getName();
        log.info("方法{}已经执行完成",method);
    }

    @AfterReturning(pointcut = "pointCut()",returning = "result")
    public  void doAfterReturning(JoinPoint joinPoint,Object result)
    {
        log.info("============doAfterReturning执行====");
        Signature signature=joinPoint.getSignature();
        String method=signature.getName();
        log.info("方法{}已经执行完成,返回值参数为{}",method,result);
        //实际项目中，可以根据业务做具体的返回值增强
    }

    @AfterThrowing(pointcut = "pointCut()",throwing = "ex")
    public  void afterThrowing(JoinPoint joinPoint,Throwable ex)
    {
        log.info("============afterThrowing执行====");
        Signature signature=joinPoint.getSignature();
        String method=signature.getName();

        //处理异常逻辑
        log.info("方法{}已经执行,异常为{}",method,ex);

    }
}
